package cn.openea.perpartner.minrest.filter;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import cn.openea.perpartner.common.core.utils.StringUtils;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author Weird077
 * @description TODO
 * @date 2022-05-25 14:03
 */
public class MinRestFilter implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        HttpServletResponse httpResponse = (HttpServletResponse) response;
        String path = httpRequest.getRequestURI();
        //获取开始时间
        long startTime = System.currentTimeMillis();
        httpRequest.setCharacterEncoding("UtF-8");
        // 设置默认的响应头类型
        httpResponse.setContentType("text/json;charset=UTF-8");
        if (path.indexOf("/minrest") > -1) {
            Map<String, Object> paramMap = new HashMap<>();
            if ("application/json".equals(httpRequest.getContentType())){
                String body_params = httpRequest.getReader().lines().collect(Collectors.joining(System.lineSeparator()));
                JSONObject bodyObj = JSONObject.parseObject(body_params);
                for(Map.Entry<String, Object> entry : bodyObj.entrySet()) {
                    paramMap.put(entry.getKey(), entry.getValue());
                }
            }else {
                paramMap = parameterMap2HashMap(httpRequest);
            }
            paramMap.put("startTime",startTime);
            String[] oldParam = new String[]{JSON.toJSONString(paramMap)};
            Map<String,Object> newParamMap = new HashMap<>();
            newParamMap.put("formData",oldParam);
            ParameterRequestWrapper  requestWrapper = new ParameterRequestWrapper(httpRequest,newParamMap);
            Set<String> keySet = paramMap.keySet();
            path += (keySet.contains("pageNum") || keySet.contains("pageSize")) ? "/getList" : "";
            httpRequest.getRequestDispatcher(path).forward(requestWrapper, httpResponse);
        } else {
            chain.doFilter(request, response);
        }
    }

    public Map<String,Object> parameterMap2HashMap(HttpServletRequest request) {
        HashMap<String, Object> param = new HashMap<>();
        Map<String, String[]> mapData = request.getParameterMap();
        Iterator<Map.Entry<String, String[]>> it = mapData.entrySet().iterator();
        while (it.hasNext()){
            Map.Entry<String, String[]> entry = it.next();
            for (String v: entry.getValue()){
                param.put(entry.getKey(), StringUtils.isBlank(v)?"":v);
            }
        }
        return param;
    }

    class ParameterRequestWrapper extends HttpServletRequestWrapper {

        private Map<String, String[]> params = new HashMap<>();

        private ParameterRequestWrapper(HttpServletRequest request) {
            // 将request交给父类，以便于调用对应方法的时候，将其输出，其实父亲类的实现方式和第一种new的方式类似
            super(request);
            //将参数表，赋予给当前的Map以便于持有request中的参数
            this.params.putAll(request.getParameterMap());
        }
        private ParameterRequestWrapper(HttpServletRequest request, Map<String, Object> newParams) {
            super(request);
            this.params.putAll(request.getParameterMap());
            addAllParameters(newParams);//这里将扩展参数写入参数表
        }

        @Override
        public Map<String, String[]> getParameterMap() {

            Map<String, String[]> returnMap = new HashMap<>();
            for (String key : params.keySet()) {
                returnMap.put(key, getParameterValues(key));
            }

            return returnMap;
        }

        @Override
        public Enumeration getParameterNames() {
            Vector l = new Vector(params.keySet());
            return l.elements();
        }


        @Override
        public String[] getParameterValues(String name) {
            Object v = params.get(name);
            if (v == null) {
                return null;
            } else if (v instanceof String[]) {
                return (String[]) v;
            } else if (v instanceof String) {
                return new String[] { (String) v };
            } else {
                return new String[] { v.toString() };
            }
        }


        @Override
        public String getParameter(String name) {
            Object v = params.get(name);
            if (v == null) {
                return null;
            } else if (v instanceof String[]) {
                String[] strArr = (String[]) v;
                if (strArr.length > 0) {
                    return strArr[0];
                } else {
                    return null;
                }
            } else if (v instanceof String) {
                return (String) v;
            } else {
                return v.toString();
            }
        }
        private void addAllParameters(Map<String, Object> newParams) {
            for(Map.Entry<String , Object>entry : newParams.entrySet()) {
                addParameter(entry.getKey() , entry.getValue());
            }
        }
        private void addParameter(String key, Object value) {
            if(value != null) {
                if(value instanceof ArrayList){
                    String value1 = String.valueOf(value).substring(1,String.valueOf(value).length());
                    value = value1.substring(0,value1.length()-1);
                    params.put(key , new String[] {(String)value});
                }
                else if(value instanceof String[]) {
                    params.put(key , (String[]) value);
                }else if(value instanceof String) {
                    params.put(key , new String[] {(String)value});
                }else {
                    params.put(key , new String[] {String.valueOf(value)});
                }
            }
        }

    }
}
